package com.bracelet.util.netty;

import cn.hutool.core.util.StrUtil;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
public class NettySessionManager {

    private static Map<String, NettySession> sessionMap = new ConcurrentHashMap<>();

    private static Map<String, Set<String>> bizMap = new ConcurrentHashMap<>();

    public static Map<String, NettySession> getSessionMap() {
        return sessionMap;
    }

    public static Map<String, Set<String>> getBizMap() {
        return bizMap;
    }

    public static void addSession(NettySession session) {
        if (session == null) {
            return;
        }

        String bizKey = session.getBizKey();
        if (StrUtil.isBlank(bizKey)) {
            return;
        }

        String sessionId = session.getChannelId();
        if (StrUtil.isBlank(sessionId)) {
            return;
        }

        sessionMap.put(sessionId, session);
        log.info("-------------新增客户端连接【addSession】，sessionId:{}，session:{}----------------", sessionId, session);

        bizMap.compute(bizKey, (key, sessionIdSet) -> {
            if (sessionIdSet == null) {
                sessionIdSet = ConcurrentHashMap.newKeySet();
            }
            sessionIdSet.add(sessionId);
            log.info("-------------新增客户端连接【addSession】，bizMap:{}，bizKey:{}，sessionIdSet:{}----------------", bizMap, key, sessionIdSet);
            return sessionIdSet;
        });
    }

    public static void removeSession(NettySession session) {
        if (session == null) {
            return;
        }

        removeSession(session.getChannel());
    }

    public static void removeSession(ChannelHandlerContext ctx) {
        if (ctx == null) {
            return;
        }
        log.info("Removing session for ChannelHandlerContext: {}", ctx);
        removeSession(ctx.channel());
    }

    public static void removeSession(Channel channel) {
        if (channel == null) {
            return;
        }

        String channelId = channel.id()
                .asLongText();
        log.info("Removing session for Channel: {}", channelId);
        removeSession(channelId);
    }

    public static void removeSession(String channelId) {
        if (StrUtil.isEmpty(channelId)) {
            return;
        }
        String trimmedChannelId = channelId.trim();
        log.info("Removing session for Channel ID: {}", trimmedChannelId);

        NettySession session = sessionMap.remove(trimmedChannelId);
        if (session == null) {
            log.info("No session found for Channel ID: {}", trimmedChannelId);
            return;
        }

        String bizKey = session.getBizKey();
        if (StrUtil.isBlank(bizKey)) {
            log.info("No bizKey found for Channel ID: {}", trimmedChannelId);
            return;
        }
        log.info("Removing bizKey: {} for Channel ID: {}", bizKey, trimmedChannelId);
        bizMap.computeIfPresent(bizKey, (key, sessionIdSet) -> {
            sessionIdSet.remove(trimmedChannelId);
            log.info("Removed session ID from bizKey: {}. Remaining session IDs: {}", bizKey, sessionIdSet);
            return sessionIdSet.isEmpty() ? null : sessionIdSet;
        });

        // Ensure channel is fully closed
        Channel channel = session.getChannel();
        if (channel != null && channel.isActive()) {
            log.info("Closing channel associated with session: {}", trimmedChannelId);
            channel.close();
        }
    }

    public static boolean isExistChannelId(ChannelHandlerContext ctx ){
        if (ctx == null) {
            return false;
        }
        return isExistChannelId(ctx.channel());
    }
    public static boolean isExistChannelId(Channel channel){
        if (channel == null) {
            return false;
        }
        String channelId=channel.id().asLongText();
        return isExistChannelId(channelId);
    }
    public static boolean isExistChannelId(String channelId){
        return sessionMap.containsKey(channelId);
    }

    public static Optional<NettySession> getSession(ChannelHandlerContext ctx) {
        if (ctx == null) {
            return Optional.empty();
        }

        return getSession(ctx.channel());
    }

    public static Optional<NettySession> getSession(Channel channel) {
        if (channel == null) {
            return Optional.empty();
        }

        String channelId = channel.id()
                .asLongText();

        return getSession(channelId);
    }

    public static Optional<NettySession> getSession(String channelId) {
        if (StrUtil.isEmpty(channelId)) {
            return Optional.empty();
        }

        if (!sessionMap.containsKey(channelId)) {
            return Optional.empty();
        }

        NettySession nettySession = sessionMap.get(channelId);
        if (nettySession == null) {
            return Optional.empty();
        }

        return Optional.of(nettySession);
    }

    /**
     * 根据BizKey获取Session列表，可能为null
     * @param bizKey
     * @return
     */
    public static List<NettySession> getSessionByBizKey(String bizKey) {
        if (StrUtil.isBlank(bizKey)) {
            return Collections.emptyList();
        }

        if (!bizMap.containsKey(bizKey)) {
            return Collections.emptyList();
        }

        Set<String> idList = bizMap.get(bizKey);
        if (idList == null || idList.isEmpty()) {
            bizMap.remove(bizKey);
            return Collections.emptyList();
        }

        List<NettySession> list = new ArrayList<>();
        for (String id : idList) {
            Optional<NettySession> op = getSession(id);
            op.ifPresent(list::add);
        }
        return list;
    }

    public static boolean isHaveSessionId(String bizKey){
        Set<String> idList = bizMap.get(bizKey);
        if (idList == null || idList.isEmpty()) {
            return true;
        }
        return false;
    }
}
